package part17_策略模式_鸭子问题.策略加工厂解决ifelse.strategy;

import part17_策略模式_鸭子问题.策略加工厂解决ifelse.pojo.LeaveForm;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName: AuditStrategyFactory
 * @Author: AllenSun
 * @Date: 2023/2/11 下午10:25
 */
public class AuditStrategyFactory {
    // 单例工厂
    private final static AuditStrategyFactory FACTORY = new AuditStrategyFactory();

    // 创建一个list存放所有的策略类
    private List<AuditStrategy> auditStrategyList = new ArrayList<>();

    // 在构造器初始化里将所有策略类放入list中存放
    private AuditStrategyFactory() {
        auditStrategyList.add(new AuditStrategyImpl_01());
        auditStrategyList.add(new AuditStrategyImpl_02());
        auditStrategyList.add(new AuditStrategyImpl_03());
        auditStrategyList.add(new AuditStrategyImpl_04());
        auditStrategyList.add(new AuditStrategyImpl_05());
    }

    // 暴露一个方法，供外界获取单例工厂
    public static AuditStrategyFactory getInstance(){
        return FACTORY;
    };

    // 根据请假单的信息，返回对应的策略方法
    public AuditStrategy getAuditStrategy(LeaveForm leaveForm) {
        AuditStrategy auditStrategy = null;
        // 遍历list里的所有策略类，判断条件是否匹配
        for (AuditStrategy strategy : auditStrategyList) {
            // 如果策略的条件跟请假单的条件相符
            if(strategy.isSupport(leaveForm)){
                if(auditStrategy==null){
                    // 获得目标策略类
                    auditStrategy=strategy;
                } else {
                    // 判断策略的优先级
                    if(strategy.getPriority()==auditStrategy.getPriority()){
                        // 如果两个策略类的优先级相同，则抛出异常
                        throw new RuntimeException("["+auditStrategy.getName()+"]:["+strategy.getName()+"]规则冲突，请尽快解决。");
                    } else if(strategy.getPriority()>auditStrategy.getPriority()){
                        auditStrategy=strategy;
                    } else {
                        //do nothing
                    }
                }
            }
        }
        if(auditStrategy==null){
            throw new RuntimeException("没有匹配的请假审核规则");
        } else {
            // 返回最终获取到的策略类
            return auditStrategy;
        }
    }
}
